

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public abstract class NodeBase
{
    protected NodeBase parent;
    protected List<NodeBase> children = new List<NodeBase>();

    public string Tag { get; set; }
    public bool HasGameObject { get; protected set; }
    public Transform Tf { get; protected set; }
    public bool IsActive { get; set; }

    #region 生命周期

    public virtual void OnInit() { }
    public virtual void OnUpdate() { }
    public virtual void OnLateUpdate() { }
    public virtual void OnFixedUpdate() { }
    public virtual void OnDestroy() 
    {
        // 注销所有事件监听
        UnlistenAll(); 
    }

    public void Update()
    {
        OnUpdate();
        foreach (var child in children)
        {
            try
            {
                if (child == null || !child.IsActive)
                    continue;
                child.Update();
            }
            catch (System.Exception ex)
            {
                child?.LogError($"Error in child node update: {ex.Message}");
            }
        }
    }

    public void LateUpdate()
    {
        OnLateUpdate();
        foreach (var child in children)
        {
            try
            {
                if (child == null || !child.IsActive)
                    continue;
                child.LateUpdate(); 
            }
            catch (System.Exception ex)
            {
                child?.LogError($"Error in child node late update: {ex.Message}");
            }
        }
    }

    public void FixedUpdate()
    {
        OnFixedUpdate();
        foreach (var child in children)
        {
            try
            {
                if (child == null || !child.IsActive)
                    continue;
                child.FixedUpdate(); 
            }
            catch (System.Exception ex)
            {
                child?.LogError($"Error in child node fixed update: {ex.Message}");
            }
        }
    }

    #endregion

    #region 协程
    public Coroutine StartCoroutine(IEnumerator routine)
    {
        // 实际调用RootNode的StartCoroutine
        return RootNode.Instance?.StartRootCoroutine(routine);
    }

    public void StopCoroutine(Coroutine routine)
    {
        RootNode.Instance?.StopRootCoroutine(routine);
    }

    #endregion

    #region Log

    public void Log(string message)
    {
        Debug.Log($"[{Tag}] {message}");
    }
    
    public void LogWarning(string message)
    {
        Debug.LogWarning($"[{Tag}] {message}");
    }

    public void LogError(string message)
    {
        Debug.LogError($"[{Tag}] {message}");
    }

    #endregion

    #region 添加/移除子节点
    public void AddChild(NodeBase child, bool hasGameObjact = true)
    {
        if (child == null || children.Contains(child))
            return;
        child.parent = this;
        child.IsActive = true;
        children.Add(child);
        if (string.IsNullOrEmpty(child.Tag))
        {
            child.Tag = child.GetType().Name;
        }
        if (HasGameObject && hasGameObjact)
        {
            child.HasGameObject = true;
            // 为子节点创建GameObject
            GameObject go = new GameObject(child.Tag);
            child.Tf = go.transform;
            child.Tf.position = Vector3.zero;
            child.Tf.rotation = Quaternion.identity;
            child.Tf.localScale = Vector3.one;
            child.Tf.SetParent(this.Tf, false);
        }
        try
        {
            child.OnInit();
        }
        catch (System.Exception ex)
        {
            child.LogError($"Error in child node OnInit: {ex.Message}");
        }
    }

    public void RemoveNode()
    {
        if (children != null && children.Count > 0)
        {
            foreach (var child in children)
            {
                if (child == null) 
                    continue;
                child.parent = null;
                child.RemoveNode();
            }
            children.Clear();
        }

        try
        {
            OnDestroy();
        }
        catch (System.Exception ex)
        {
            LogError($"Error in OnDestroy: {ex.Message}");
        }

        if (HasGameObject && Tf != null)
        {
            GameObject.Destroy(Tf.gameObject);
        }

        parent?.children.Remove(this);
    }

    #endregion

    #region 事件

    protected void Listen<T>(T key, Action callback)
    {
        if (key == null || callback == null)
        {
            LogError("Listen key or callback is null!");
            return;
        }
        EventManager.Instance.RegisterEvent(key, callback);
    }

    protected void Listen<T, V1>(T key, Action<V1> callback)
    {
        if (key == null || callback == null)
        {
            LogError("Listen key or callback is null!");
            return;
        }
        EventManager.Instance.RegisterEvent(key, callback);
    }

    protected void Listen<T, V1, V2>(T key, Action<V1, V2> callback)
    {
        if (key == null || callback == null)
        {
            LogError("Listen key or callback is null!");
            return;
        }
        EventManager.Instance.RegisterEvent(key, callback);
    }

    protected void Listen<T, V1, V2, V3>(T key, Action<V1, V2, V3> callback)
    {
        if (key == null || callback == null)
        {
            LogError("Listen key or callback is null!");
            return;
        }
        EventManager.Instance.RegisterEvent(key, callback);
    }

    protected void Listen<T, V1, V2, V3, V4>(T key, Action<V1, V2, V3, V4> callback)
    {
        if (key == null || callback == null)
        {
            LogError("Listen key or callback is null!");
            return;
        }
        EventManager.Instance.RegisterEvent(key, callback);
    }

    protected void Listen<T, V1, V2, V3, V4, V5>(T key, Action<V1, V2, V3, V4, V5> callback)
    {
        if (key == null || callback == null)
        {
            LogError("Listen key or callback is null!");
            return;
        }
        EventManager.Instance.RegisterEvent(key, callback);
    }

    protected void Unlisten<T>(T key, Action callback)
    {
        if (key == null || callback == null)
        {
            LogError("Unlisten key or callback is null!");
            return;
        }
        EventManager.Instance.UnregisterEvent(key, callback);
    }

    protected void Unlisten<T, V1>(T key, Action<V1> callback)
    {
        if (key == null || callback == null)
        {
            LogError("Unlisten key or callback is null!");
            return;
        }
        EventManager.Instance.UnregisterEvent(key, callback);
    }

    protected void Unlisten<T, V1, V2>(T key, Action<V1, V2> callback)
    {
        if (key == null || callback == null)
        {
            LogError("Unlisten key or callback is null!");
            return;
        }
        EventManager.Instance.UnregisterEvent(key, callback);
    }

    protected void Unlisten<T, V1, V2, V3>(T key, Action<V1, V2, V3> callback)
    {
        if (key == null || callback == null)
        {
            LogError("Unlisten key or callback is null!");
            return;
        }
        EventManager.Instance.UnregisterEvent(key, callback);
    }

    protected void Unlisten<T, V1, V2, V3, V4>(T key, Action<V1, V2, V3, V4> callback)
    {
        if (key == null || callback == null)
        {
            LogError("Unlisten key or callback is null!");
            return;
        }
        EventManager.Instance.UnregisterEvent(key, callback);
    }

    protected void Unlisten<T, V1, V2, V3, V4, V5>(T key, Action<V1, V2, V3, V4, V5> callback)
    {
        if (key == null || callback == null)
        {
            LogError("Unlisten key or callback is null!");
            return;
        }
        EventManager.Instance.UnregisterEvent(key, callback);
    }

    protected void UnlistenAll()
    {
        EventManager.Instance.UnregisterEventOfTarget(this);
    }

    protected void TriggerEvent<T>(T key)
    {
        if (key == null)
        {
            LogError("TriggerEvent key is null!");
            return;
        }
        EventManager.Instance.TriggerEvent(key);
    }

    protected void TriggerEvent<T, V1>(T key, V1 arg1)
    {
        if (key == null)
        {
            LogError("TriggerEvent key is null!");
            return;
        }
        EventManager.Instance.TriggerEvent(key, arg1);
    }

    protected void TriggerEvent<T, V1, V2>(T key, V1 arg1, V2 arg2)
    {
        if (key == null)
        {
            LogError("TriggerEvent key is null!");
            return;
        }
        EventManager.Instance.TriggerEvent(key, arg1, arg2);
    }

    protected void TriggerEvent<T, V1, V2, V3>(T key, V1 arg1, V2 arg2, V3 arg3)
    {
        if (key == null)
        {
            LogError("TriggerEvent key is null!");
            return;
        }
        EventManager.Instance.TriggerEvent(key, arg1, arg2, arg3);
    }

    protected void TriggerEvent<T, V1, V2, V3, V4>(T key, V1 arg1, V2 arg2, V3 arg3, V4 arg4)
    {
        if (key == null)
        {
            LogError("TriggerEvent key is null!");
            return;
        }
        EventManager.Instance.TriggerEvent(key, arg1, arg2, arg3, arg4);
    }

    protected void TriggerEvent<T, V1, V2, V3, V4, V5>(T key, V1 arg1, V2 arg2, V3 arg3, V4 arg4, V5 arg5)
    {
        if (key == null)
        {
            LogError("TriggerEvent key is null!");
            return;
        }
        EventManager.Instance.TriggerEvent(key, arg1, arg2, arg3, arg4, arg5);
    }

    #endregion

}
